package com.acme.bankapp.domain.client;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import com.acme.bankapp.domain.account.Account;

/**
 * Class is a presentation of the client.
 *
 * @author S.Zhidkov
 */
public class Client implements Serializable {

    private static final String EMPTY_STRING = "";
    private static final String ERROR_NAME = "Incorrect client name!";
    private static final String ERROR_GENDER = "Incorrect client gender!";

    private String name;
    private Gender gender;
    private Set<Account> accounts = new HashSet<Account>();
    private String emailAddress;

    /**
     * Creates new client.
     *
     * @param name name of the client
     * @param gender gender of the client
     * @throws IllegalArgumentException if name, age, or gender is incorrect
     */
    public Client(final String name, final Gender gender) {
        if ((name == null) || (EMPTY_STRING.equals(name))) {
            throw new IllegalArgumentException(ERROR_NAME);
        }

        if (gender == null) {
            throw new IllegalArgumentException(ERROR_GENDER);
        }

        this.name = name;
        this.gender = gender;
    }

    /**
     * Returns name of the client.
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * Returns all accounts of the client.
     *
     * @return account of the client
     */
    public Set<Account> getAccounts() {
        return Collections.unmodifiableSet(accounts);
    }

    /**
     * Returns email of the client.
     *
     * @return email address string
     */
    public String getEmailAddress() {
        return emailAddress;
    }

    /**
     * Set clients email address.
     *
     * @param emailAddress
     */
    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    /**
     * Returns client salutation.
     *
     * @return String
     */
    public String getClientSalutation() {
        return gender.getSalutation();
    }

    /**
     * Method adds account to the client.
     *
     * @param account
     */
    public void addAccount(Account account) {
        accounts.add(account);
    }

    /**
     * Method returns maximum amount that we can withdraw from the all accounts of this client.
     *
     * @return
     */
    public double maximumAmountToWithdraw() {
        double sum = 0;
        for (Account account : accounts) {
            sum += account.maximumAmountToWithdraw();
        }
        return sum;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 37*result + name.hashCode();
        result = 37*result + gender.hashCode();
        return result;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (!(o instanceof Client)) { return false; }

        final Client c = (Client) o;
        return  (name.equals(c.name)) && (gender == c.gender);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(gender.getSalutation()).append(" ").append(name);
        sb.append(": [gender: ").append(gender);
        sb.append("] [email: ").append(emailAddress).append("] ");
        sb.append(accounts);
        return sb.toString();
    }
}
